<!DOCTYPE html><html lang="en" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Sobremesa的个人空间 - 重邮小废物</title><meta name="keywords" content="Sobremesa"><meta name="author" content="Li YunBO"><meta name="copyright" content="Li YunBO"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta http-equiv="Cache-Control" content="no-transform"><meta http-equiv="Cache-Control" content="no-siteapp"><meta name="description" content="给自己的警言：不要止步不前，不要因循守缺，不要纸上谈兵，不要不思进取，不要一直不要！">
<meta property="og:type" content="website">
<meta property="og:title" content="Sobremesa的个人空间">
<meta property="og:url" content="http://example.com/index.html">
<meta property="og:site_name" content="Sobremesa的个人空间">
<meta property="og:description" content="给自己的警言：不要止步不前，不要因循守缺，不要纸上谈兵，不要不思进取，不要一直不要！">
<meta property="og:locale" content="en_US">
<meta property="og:image" content="http://example.com/img/%E5%A4%B4%E5%83%8F2.jpg">
<meta property="article:author" content="Li YunBO">
<meta property="article:tag" content="Sobremesa">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="http://example.com/img/%E5%A4%B4%E5%83%8F2.jpg"><link rel="shortcut icon" href="/img/favicon.png"><link rel="canonical" href="http://example.com/"><link rel="preconnect" href="//cdn.jsdelivr.net"/><link rel="preconnect" href="//busuanzi.ibruce.info"/><link rel="stylesheet" href="/css/index.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free/css/all.min.css"><script>var GLOBAL_CONFIG = { 
  root: '/',
  algolia: undefined,
  localSearch: undefined,
  translate: undefined,
  noticeOutdate: undefined,
  highlight: {"plugin":"highlighjs","highlightCopy":true,"highlightLang":true},
  copy: {
    success: 'Copy successfully',
    error: 'Copy error',
    noSupport: 'The browser does not support'
  },
  relativeDate: {
    homepage: false,
    post: false
  },
  runtime: '',
  date_suffix: {
    just: 'Just',
    min: 'minutes ago',
    hour: 'hours ago',
    day: 'days ago',
    month: 'months ago'
  },
  copyright: undefined,
  ClickShowText: undefined,
  lightbox: 'fancybox',
  Snackbar: undefined,
  source: {
    jQuery: 'https://cdn.jsdelivr.net/npm/jquery@latest/dist/jquery.min.js',
    justifiedGallery: {
      js: 'https://cdn.jsdelivr.net/npm/justifiedGallery/dist/js/jquery.justifiedGallery.min.js',
      css: 'https://cdn.jsdelivr.net/npm/justifiedGallery/dist/css/justifiedGallery.min.css'
    },
    fancybox: {
      js: 'https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@latest/dist/jquery.fancybox.min.js',
      css: 'https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@latest/dist/jquery.fancybox.min.css'
    }
  },
  isPhotoFigcaption: false,
  islazyload: false,
  isanchor: false
};

var saveToLocal = {
  set: function setWithExpiry(key, value, ttl) {
    const now = new Date()
    const expiryDay = ttl * 86400000
    const item = {
      value: value,
      expiry: now.getTime() + expiryDay,
    }
    localStorage.setItem(key, JSON.stringify(item))
  },

  get: function getWithExpiry(key) {
    const itemStr = localStorage.getItem(key)

    if (!itemStr) {
      return undefined
    }
    const item = JSON.parse(itemStr)
    const now = new Date()

    if (now.getTime() > item.expiry) {
      localStorage.removeItem(key)
      return undefined
    }
    return item.value
  }
}

// https://stackoverflow.com/questions/16839698/jquery-getscript-alternative-in-native-javascript
const getScript = url => new Promise((resolve, reject) => {
  const script = document.createElement('script')
  script.src = url
  script.async = true
  script.onerror = reject
  script.onload = script.onreadystatechange = function() {
    const loadState = this.readyState
    if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
    script.onload = script.onreadystatechange = null
    resolve()
  }
  document.head.appendChild(script)
})</script><script id="config_change">var GLOBAL_CONFIG_SITE = { 
  isPost: false,
  isHome: true,
  isHighlightShrink: false,
  isToc: false,
  postUpdate: '2021-09-16 17:01:01'
}</script><noscript><style type="text/css">
  #nav {
    opacity: 1
  }
  .justified-gallery img {
    opacity: 1
  }

  #recent-posts time,
  #post-meta time {
    display: inline !important
  }
</style></noscript><script>(function () {  window.activateDarkMode = function () {
    document.documentElement.setAttribute('data-theme', 'dark')
    if (document.querySelector('meta[name="theme-color"]') !== null) {
      document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
    }
  }
  window.activateLightMode = function () {
    document.documentElement.setAttribute('data-theme', 'light')
   if (document.querySelector('meta[name="theme-color"]') !== null) {
      document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff')
    }
  }
  const autoChangeMode = 'false'
  const t = saveToLocal.get('theme')
  if (autoChangeMode === '1') {
    const isDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches
    const isLightMode = window.matchMedia('(prefers-color-scheme: light)').matches
    const isNotSpecified = window.matchMedia('(prefers-color-scheme: no-preference)').matches
    const hasNoSupport = !isDarkMode && !isLightMode && !isNotSpecified
    if (t === undefined) {
      if (isLightMode) activateLightMode()
      else if (isDarkMode) activateDarkMode()
      else if (isNotSpecified || hasNoSupport) {
        const now = new Date()
        const hour = now.getHours()
        const isNight = hour <= 6 || hour >= 18
        isNight ? activateDarkMode() : activateLightMode()
      }
      window.matchMedia('(prefers-color-scheme: dark)').addListener(function (e) {
        if (saveToLocal.get('theme') === undefined) {
          e.matches ? activateDarkMode() : activateLightMode()
        }
      })
    } else if (t === 'light') activateLightMode()
    else activateDarkMode()
  } else if (autoChangeMode === '2') {
    const now = new Date()
    const hour = now.getHours()
    const isNight = hour <= 6 || hour >= 18
    if (t === undefined) isNight ? activateDarkMode() : activateLightMode()
    else if (t === 'light') activateLightMode()
    else activateDarkMode()
  } else {
    if (t === 'dark') activateDarkMode()
    else if (t === 'light') activateLightMode()
  }const asideStatus = saveToLocal.get('aside-status')
if (asideStatus !== undefined) {
   if (asideStatus === 'hide') {
     document.documentElement.classList.add('hide-aside')
   } else {
     document.documentElement.classList.remove('hide-aside')
   }
}})()</script><meta name="generator" content="Hexo 5.4.0"><link rel="alternate" href="/atom.xml" title="Sobremesa的个人空间" type="application/atom+xml">
</head><body><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="author-avatar"><img class="avatar-img" src="/img/%E5%A4%B4%E5%83%8F2.jpg" onerror="onerror=null;src='/img/friend_404.gif'" alt="avatar"/></div><div class="site-data"><div class="data-item is-center"><div class="data-item-link"><a href="/archives/"><div class="headline">Articles</div><div class="length-num">193</div></a></div></div><div class="data-item is-center"><div class="data-item-link"><a href="/tags/"><div class="headline">Tags</div><div class="length-num">25</div></a></div></div><div class="data-item is-center"><div class="data-item-link"><a href="/categories/"><div class="headline">Categories</div><div class="length-num">18</div></a></div></div></div><hr/><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 首页</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> 档案</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></div><div class="menus_item"><a class="site-page" href="/categories/"><i class="fa-fw fas fa-folder-open"></i><span> 分类</span></a></div><div class="menus_item"><a class="site-page" href="javascript:void(0);"><i class="fa-fw fas fa-list"></i><span> 娱乐</span><i class="fas fa-chevron-down expand"></i></a><ul class="menus_item_child"><li><a class="site-page" href="/music/"><i class="fa-fw fas fa-music"></i><span> Music</span></a></li><li><a class="site-page" href="/movies/"><i class="fa-fw fas fa-video"></i><span> Movie</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="/link/"><i class="fa-fw fas fa-link"></i><span> 友链</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> 关于</span></a></div></div></div></div><div id="body-wrap"><header class="full_page" id="page-header" style="background-image: url(/img/%E6%9E%97%E5%85%81%E5%84%BF.jpg)"><nav id="nav"><span id="blog_name"><a id="site-name" href="/">Sobremesa的个人空间</a></span><div id="menus"><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 首页</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> 档案</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></div><div class="menus_item"><a class="site-page" href="/categories/"><i class="fa-fw fas fa-folder-open"></i><span> 分类</span></a></div><div class="menus_item"><a class="site-page" href="javascript:void(0);"><i class="fa-fw fas fa-list"></i><span> 娱乐</span><i class="fas fa-chevron-down expand"></i></a><ul class="menus_item_child"><li><a class="site-page" href="/music/"><i class="fa-fw fas fa-music"></i><span> Music</span></a></li><li><a class="site-page" href="/movies/"><i class="fa-fw fas fa-video"></i><span> Movie</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="/link/"><i class="fa-fw fas fa-link"></i><span> 友链</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> 关于</span></a></div></div><div id="toggle-menu"><a class="site-page"><i class="fas fa-bars fa-fw"></i></a></div></div></nav><div id="site-info"><h1 id="site-title">Sobremesa的个人空间</h1><div id="site-subtitle"><span id="subtitle"></span></div><div id="site_social_icons"><a class="social-icon" href="https://gitee.com/Sobremesa_bolg" target="_blank" title="Gitee"><i class="fab fa-github"></i></a></div></div><div id="scroll-down"><i class="fas fa-angle-down scroll-down-effects"></i></div></header><main class="layout" id="content-inner"><div class="recent-posts" id="recent-posts"><div class="recent-post-item"><div class="post_cover left_radius"><a href="/2021/08/16/%E6%B5%8B%E8%AF%95%E8%AE%B0%E5%BD%95/" title="测试">     <img class="post_bg" src="/img/%E5%92%8C%E6%9C%8D%E5%B0%91%E5%A5%B3.jpg%20img/%E8%9C%98%E8%9B%9B%E4%BE%A0.jpg" onerror="this.onerror=null;this.src='/img/404.png'" alt="测试"></a></div><div class="recent-post-info"><a class="article-title" href="/2021/08/16/%E6%B5%8B%E8%AF%95%E8%AE%B0%E5%BD%95/" title="测试">测试</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">Created</span><time datetime="2021-08-16T01:20:46.666Z" title="Created 2021-08-16 09:20:46">2021-08-16</time></span></div><div class="content">成果与否</div></div></div><div class="recent-post-item"><div class="post_cover right_radius"><a href="/2021/08/16/%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E9%81%8D%E5%8E%86/" title="二叉树的遍历">     <img class="post_bg" src="/img/%E5%92%8C%E6%9C%8D%E5%B0%91%E5%A5%B3.jpg%20img/%E8%9C%98%E8%9B%9B%E4%BE%A0.jpg" onerror="this.onerror=null;this.src='/img/404.png'" alt="二叉树的遍历"></a></div><div class="recent-post-info"><a class="article-title" href="/2021/08/16/%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E9%81%8D%E5%8E%86/" title="二叉树的遍历">二叉树的遍历</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">Created</span><time datetime="2021-08-15T16:00:00.000Z" title="Created 2021-08-16 00:00:00">2021-08-16</time></span><span class="article-meta"><span class="article-meta__separator">|</span><i class="fas fa-inbox article-meta__icon"></i><a class="article-meta__categories" href="/categories/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/">数据结构</a></span></div><div class="content">二叉树的遍历概述二叉树的遍历是一个很常见的问题。二叉树的遍历方式主要有：先序遍历、中序遍历、后序遍历、层次遍历。先序、中序、后序其实指的是父节点被访问的次序。若在遍历过程中，父节点先于它的子节点被访问，就是先序遍历；父节点被访问的次序位于左右孩子节点之间，就是中序遍历；访问完左右孩子节点之后再访问父节点，就是后序遍历。不论是先序遍历、中序遍历还是后序遍历，左右孩子节点的相对访问次序是不变的，总是先访问左孩子节点，再访问右孩子节点。而层次遍历，就是按照从上到下、从左向右的顺序访问二叉树的每个节点。


简单概括：
先序遍历：遍历顺序规则为【根左右】
中序遍历：遍历顺序规则为【左根右】
后序遍历：遍历顺序规则为【左右根】
举例说明：

先序遍历：ABCDEFGHK    先访问根节点，然后是根节点的左子节点，直至没有左子节点，开始右子节点
中序遍历：BDCAEHGKF    先访问最左子节点，没有则访问根节点，然后再右节点，以此遍历
后续遍历：DCBHKGFEA    先左节点，再右节点，在跟节点
以中序遍历为例：
中序遍历的规则是【左根右】，我们从root节点A看起；
此时A是根节点，遍 ...</div></div></div><div class="recent-post-item"><div class="post_cover left_radius"><a href="/2021/08/10/%E8%AE%A4%E7%9C%9F%E7%9A%84+Netty+%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90%EF%BC%88%E4%BA%8C%EF%BC%89/" title="认真的 Netty 源码解析（二）">     <img class="post_bg" src="/img/%E5%92%8C%E6%9C%8D%E5%B0%91%E5%A5%B3.jpg%20img/%E8%9C%98%E8%9B%9B%E4%BE%A0.jpg" onerror="this.onerror=null;this.src='/img/404.png'" alt="认真的 Netty 源码解析（二）"></a></div><div class="recent-post-info"><a class="article-title" href="/2021/08/10/%E8%AE%A4%E7%9C%9F%E7%9A%84+Netty+%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90%EF%BC%88%E4%BA%8C%EF%BC%89/" title="认真的 Netty 源码解析（二）">认真的 Netty 源码解析（二）</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">Created</span><time datetime="2021-08-10T07:53:27.000Z" title="Created 2021-08-10 15:53:27">2021-08-10</time></span></div><div class="content">Channel 的 register 操作经过前面的铺垫，我们已经具备一定的基础了，我们开始来把前面学到的内容揉在一起。这节，我们会介绍 register 操作，这一步其实是非常关键的，对于我们源码分析非常重要。
register我们从 EchoClient 中的 connect() 方法出发，或者 EchoServer 的 bind(port) 方法出发，都会走到 initAndRegister() 这个方法：
123456789101112131415161718192021final ChannelFuture initAndRegister() &#123;    Channel channel = null;    try &#123;        // 1        channel = channelFactory.newChannel();        // 2 对于 Bootstrap 和 ServerBootstrap，这里面有些不一样        init(channel);    &#125; catch (Throwable t) &#123;     ...</div></div></div><div class="recent-post-item"><div class="post_cover right_radius"><a href="/2021/08/10/%E8%AE%A4%E7%9C%9F%E7%9A%84+Netty+%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90%EF%BC%88%E4%B8%80%EF%BC%89/" title="认真的 Netty 源码解析（一）">     <img class="post_bg" src="/img/%E5%92%8C%E6%9C%8D%E5%B0%91%E5%A5%B3.jpg%20img/%E8%9C%98%E8%9B%9B%E4%BE%A0.jpg" onerror="this.onerror=null;this.src='/img/404.png'" alt="认真的 Netty 源码解析（一）"></a></div><div class="recent-post-info"><a class="article-title" href="/2021/08/10/%E8%AE%A4%E7%9C%9F%E7%9A%84+Netty+%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90%EF%BC%88%E4%B8%80%EF%BC%89/" title="认真的 Netty 源码解析（一）">认真的 Netty 源码解析（一）</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">Created</span><time datetime="2021-08-10T07:53:15.000Z" title="Created 2021-08-10 15:53:15">2021-08-10</time></span></div><div class="content">2019-04-08 更新：为了增强该文章的可读性，我重新梳理了一遍，更新了少量内容，并且将原来长长的文章拆分为多篇文章，这样有利于读者阅读。请移步: 《Netty 源码解析系列》
本文又是一篇源码分析文章，其实除了 Doug Lea 的并发包源码，我是真不太爱写源码分析。因为要花非常多的时间，而且很多地方需要反复组织语言。
本文将介绍 Netty，Java 平台上使用最广泛的 NIO 包，它是对 JDK 中的 NIO 实现的一层封装，让我们能更方便地开发 NIO 程序。其实，Netty 不仅仅是 NIO 吧，但是，基本上大家都冲着 NIO 来的。
个人感觉国内对于 Netty 的吹嘘是有点过了，主要是很多人靠它吃饭，要么是搞培训的，要么是出书的，恨不得把 Netty 吹上天去，这种现象也是挺不好的，反而使得初学者觉得 Netty 是什么高深的技术一样。
Netty 的源码不是很简单，因为它比较多，而且各个类之间的关系错综复杂，很多人说它的源码很好，这点我觉得一般，真要说好代码，还得 Doug Lea 的并发源码比较漂亮，一行行都是精华，不过它们是不同类型的，也没什么好对比的。Nett ...</div></div></div><div class="recent-post-item"><div class="post_cover left_radius"><a href="/2021/08/10/Java+%E9%9D%9E%E9%98%BB%E5%A1%9E+IO+%E5%92%8C%E5%BC%82%E6%AD%A5+IO/" title="Java 非阻塞 IO 和异步 IO">     <img class="post_bg" src="/img/%E5%92%8C%E6%9C%8D%E5%B0%91%E5%A5%B3.jpg%20img/%E8%9C%98%E8%9B%9B%E4%BE%A0.jpg" onerror="this.onerror=null;this.src='/img/404.png'" alt="Java 非阻塞 IO 和异步 IO"></a></div><div class="recent-post-info"><a class="article-title" href="/2021/08/10/Java+%E9%9D%9E%E9%98%BB%E5%A1%9E+IO+%E5%92%8C%E5%BC%82%E6%AD%A5+IO/" title="Java 非阻塞 IO 和异步 IO">Java 非阻塞 IO 和异步 IO</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">Created</span><time datetime="2021-08-10T07:52:59.000Z" title="Created 2021-08-10 15:52:59">2021-08-10</time></span></div><div class="content">上一篇文章介绍了 Java NIO 中 Buffer、Channel 和 Selector 的基本操作，主要是一些接口操作，比较简单。
本文将介绍非阻塞 IO 和异步 IO，也就是大家耳熟能详的 NIO 和 AIO。很多初学者可能分不清楚异步和非阻塞的区别，只是在各种场合能听到异步非阻塞这个词。
本文会先介绍并演示阻塞模式，然后引入非阻塞模式来对阻塞模式进行优化，最后再介绍 JDK7 引入的异步 IO，由于网上关于异步 IO 的介绍相对较少，所以这部分内容我会介绍得具体一些。
希望看完本文，读者可以对非阻塞 IO 和异步 IO 的迷雾看得更清晰些，或者为初学者解开一丝丝疑惑也是好的。


阻塞模式 IO我们已经介绍过使用 Java NIO 包组成一个简单的客户端-服务端网络通讯所需要的 ServerSocketChannel、SocketChannel 和 Buffer，我们这里整合一下它们，给出一个完整的可运行的例子：
1234567891011121314151617181920public class Server &#123;    public static void mai ...</div></div></div><div class="recent-post-item"><div class="post_cover right_radius"><a href="/2021/08/10/Java+NIO%EF%BC%9ABuffer%E3%80%81Channel+%E5%92%8C+Selector/" title="Java NIO：Buffer、Channel 和 Selector">     <img class="post_bg" src="/img/%E5%92%8C%E6%9C%8D%E5%B0%91%E5%A5%B3.jpg%20img/%E8%9C%98%E8%9B%9B%E4%BE%A0.jpg" onerror="this.onerror=null;this.src='/img/404.png'" alt="Java NIO：Buffer、Channel 和 Selector"></a></div><div class="recent-post-info"><a class="article-title" href="/2021/08/10/Java+NIO%EF%BC%9ABuffer%E3%80%81Channel+%E5%92%8C+Selector/" title="Java NIO：Buffer、Channel 和 Selector">Java NIO：Buffer、Channel 和 Selector</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">Created</span><time datetime="2021-08-10T07:52:48.000Z" title="Created 2021-08-10 15:52:48">2021-08-10</time></span></div><div class="content">[TOC]
本文将介绍 Java NIO 中三大组件 Buffer、Channel、Selector 的使用。
本来要一起介绍非阻塞 IO 和 JDK7 的异步 IO 的，不过因为之前的文章真的太长了，有点影响读者阅读，所以这里将它们放到另一篇文章中进行介绍。



Buffer一个 Buffer 本质上是内存中的一块，我们可以将数据写入这块内存，之后从这块内存获取数据。
java.nio 定义了以下几个 Buffer 的实现，这个图读者应该也在不少地方见过了吧。

其实核心是最后的 ByteBuffer，前面的一大串类只是包装了一下它而已，我们使用最多的通常也是 ByteBuffer。
我们应该将 Buffer 理解为一个数组，IntBuffer、CharBuffer、DoubleBuffer 等分别对应 int[]、char[]、double[] 等。
MappedByteBuffer 用于实现内存映射文件，也不是本文关注的重点。
我觉得操作 Buffer 和操作数组、类集差不多，只不过大部分时候我们都把它放到了 NIO 的场景里面来使用而已。下面介绍 Buffer 中的几个重要属 ...</div></div></div><div class="recent-post-item"><div class="post_cover left_radius"><a href="/2021/08/10/HotSpot+JVM+%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86/" title="HotSpot JVM 内存管理">     <img class="post_bg" src="/img/%E5%92%8C%E6%9C%8D%E5%B0%91%E5%A5%B3.jpg%20img/%E8%9C%98%E8%9B%9B%E4%BE%A0.jpg" onerror="this.onerror=null;this.src='/img/404.png'" alt="HotSpot JVM 内存管理"></a></div><div class="recent-post-info"><a class="article-title" href="/2021/08/10/HotSpot+JVM+%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86/" title="HotSpot JVM 内存管理">HotSpot JVM 内存管理</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">Created</span><time datetime="2021-08-10T07:52:00.000Z" title="Created 2021-08-10 15:52:00">2021-08-10</time></span></div><div class="content">关于 JVM 内存管理或者说垃圾收集，大家可能看过很多的文章了，笔者准备给大家总结下。这算是系列的第一篇，接下来一段时间会持续更新。
本文主要是翻译《Memory Management in the Java HotSpot Virtual Machine》白皮书的前四章内容，这是 2006 的老文章了，当年发布这篇文章的还是 Sun Microsystems，以后应该会越来越少人记得这家曾经无比伟大的公司了。
虽然这个白皮书有点老了，不过那个时候 Sun 在 J2SE 5.0 版本的 HotSpot 虚拟机上已经有了 Parallel 并行垃圾收集器和 CMS 这种并发收集器了，所以其实内容也没那么过时。

其实本文应该有挺多人都翻译过，我大体上是意译的，增、删了部分内容。

其他的知识，包括 Java5 之后的垃圾收集器，如 Java8 的 MetaSpace 取代了永久代、G1 收集器等，将在日后的文章中进行介绍。
目录


垃圾收集概念GC 需要做 3 件事情：

分配内存，为每个新建的对象分配空间
确保还在使用的对象的内存一直还在，不能把有用的空间当垃圾回收了
释放不再使用的 ...</div></div></div><div class="recent-post-item"><div class="post_cover right_radius"><a href="/2021/08/10/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E4%B9%9F%E5%8F%AF%E4%BB%A5%E8%BF%99%E4%B9%88%E7%AE%80%E5%8D%95/" title="设计模式也可以这么简单">     <img class="post_bg" src="/img/%E5%92%8C%E6%9C%8D%E5%B0%91%E5%A5%B3.jpg%20img/%E8%9C%98%E8%9B%9B%E4%BE%A0.jpg" onerror="this.onerror=null;this.src='/img/404.png'" alt="设计模式也可以这么简单"></a></div><div class="recent-post-info"><a class="article-title" href="/2021/08/10/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E4%B9%9F%E5%8F%AF%E4%BB%A5%E8%BF%99%E4%B9%88%E7%AE%80%E5%8D%95/" title="设计模式也可以这么简单">设计模式也可以这么简单</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">Created</span><time datetime="2021-08-10T07:51:25.000Z" title="Created 2021-08-10 15:51:25">2021-08-10</time></span><span class="article-meta"><span class="article-meta__separator">|</span><i class="fas fa-inbox article-meta__icon"></i><a class="article-meta__categories" href="/categories/design-pattern/">design pattern</a></span></div><div class="content">一直想写一篇介绍设计模式的文章，让读者可以很快看完，而且一看就懂，看懂就会用，同时不会将各个模式搞混。自认为本文还是写得不错的😂😂😂，花了不少心思来写这文章和做图，力求让读者真的能看着简单同时有所收获。
设计模式是对大家实际工作中写的各种代码进行高层次抽象的总结，其中最出名的当属 Gang of Four (GoF) 的分类了，他们将设计模式分类为 23 种经典的模式，根据用途我们又可以分为三大类，分别为创建型模式、结构型模式和行为型模式。
有一些重要的设计原则在开篇和大家分享下，这些原则将贯通全文：

面向接口编程，而不是面向实现。这个很重要，也是优雅的、可扩展的代码的第一步，这就不需要多说了吧。
职责单一原则。每个类都应该只有一个单一的功能，并且该功能应该由这个类完全封装起来。
对修改关闭，对扩展开放。对修改关闭是说，我们辛辛苦苦加班写出来的代码，该实现的功能和该修复的 bug 都完成了，别人可不能说改就改；对扩展开放就比较好理解了，也就是说在我们写好的代码基础上，很容易实现扩展。

创建型模式比较简单，但是会比较没有意思，结构型和行为型比较有意思。
创建型模式创建型模式的作 ...</div></div></div><div class="recent-post-item"><div class="post_cover left_radius"><a href="/2021/08/10/RateLimiter+%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90(Guava+%E5%92%8C+Sentinel+%E5%AE%9E%E7%8E%B0)/" title="RateLimiter 源码分析(Guava 和 Sentinel 实现)">     <img class="post_bg" src="/img/%E5%92%8C%E6%9C%8D%E5%B0%91%E5%A5%B3.jpg%20img/%E8%9C%98%E8%9B%9B%E4%BE%A0.jpg" onerror="this.onerror=null;this.src='/img/404.png'" alt="RateLimiter 源码分析(Guava 和 Sentinel 实现)"></a></div><div class="recent-post-info"><a class="article-title" href="/2021/08/10/RateLimiter+%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90(Guava+%E5%92%8C+Sentinel+%E5%AE%9E%E7%8E%B0)/" title="RateLimiter 源码分析(Guava 和 Sentinel 实现)">RateLimiter 源码分析(Guava 和 Sentinel 实现)</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">Created</span><time datetime="2021-08-10T07:51:01.000Z" title="Created 2021-08-10 15:51:01">2021-08-10</time></span></div><div class="content">本文主要介绍关于流控的两部分内容。
第一部分介绍 Guava 中 RateLimiter 的源码，包括它的两种模式，目前网上大部分文章只分析简单的 SmoothBursty 模式，而没有分析带有预热的 SmoothWarmingUp。
第二部分介绍 Sentinel 中流控的实现，本文不要求读者了解 Sentinel，这部分内容和 Sentinel 耦合很低，所以读者不需要有阅读压力。
Sentinel 中流控设计是参考 Guava RateLimiter 的，所以阅读第二部分内容，需要有第一部分内容的背景。
Guava RateLimiterRateLimiter 基于漏桶算法，但它参考了令牌桶算法，这里不讨论流控算法，请自行查找资料。
本文使用 Guava 版本是 26.0-jre。
RateLimiter 使用介绍RateLimiter 的接口非常简单，它有两个静态方法用来实例化，实例化以后，我们只需要关心 acquire 就行了，甚至都没有 release 操作。
// RateLimiter 接口列表：
1234567891011121314// 实例化的两种方式：publi ...</div></div></div><div class="recent-post-item"><div class="post_cover right_radius"><a href="/2021/08/10/%E8%81%8A%E8%81%8A+HTTPS+%E7%9A%84%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86/" title="聊聊 HTTPS 的工作原理">     <img class="post_bg" src="/img/%E5%92%8C%E6%9C%8D%E5%B0%91%E5%A5%B3.jpg%20img/%E8%9C%98%E8%9B%9B%E4%BE%A0.jpg" onerror="this.onerror=null;this.src='/img/404.png'" alt="聊聊 HTTPS 的工作原理"></a></div><div class="recent-post-info"><a class="article-title" href="/2021/08/10/%E8%81%8A%E8%81%8A+HTTPS+%E7%9A%84%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86/" title="聊聊 HTTPS 的工作原理">聊聊 HTTPS 的工作原理</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">Created</span><time datetime="2021-08-10T07:50:52.000Z" title="Created 2021-08-10 15:50:52">2021-08-10</time></span></div><div class="content">又很久没更新文章了啊……虽然这次疫情把大家都留在了家里，不过我自己的时间反而更少了，倒是花了大把的时间在峡谷的边路游走。
本文聊聊 HTTPS 的一些东西，和大家扯扯 SSL 证书的整个工作流程。希望大家有一些基本的常识：

https 使用了非对称加密和对称加密，为什么要使用对称和非对称加密？非对称加密的原理是什么？这种简单的问题默认读者已经了解了。
非对称加密涉及到一对公钥和私钥组合，它们是一一对应的关系，不存在一个私钥对应多个公钥这种情况。
CA 是 Certification Authority 的缩写，它代表世界上那些权威的证书颁发机构。

CA 需要做什么我们在申请一个 https 证书的时候，要在市场上选择一家 CA 来给你签发证书，那么 CA 的工作是什么呢？
CA 要验证这个域名真的是你的：通常就是通过 DNS 记录或者就是你在指定 URI 下放置一个特殊文件，让 CA 可以在外网环境下访问到它。
CA 是一个非常关键的角色，因为它签出来的任何证书都是被信任的，所以这要求每个 CA 都不能胡来。

试想一下，如果某个 CA 私自给某个黑客签发了 *.taobao.co ...</div></div></div><nav id="pagination"><div class="pagination"><span class="page-number current">1</span><a class="page-number" href="/page/2/">2</a><span class="space">&hellip;</span><a class="page-number" href="/page/20/">20</a><a class="extend next" rel="next" href="/page/2/"><i class="fas fa-chevron-right fa-fw"></i></a></div></nav></div><div class="aside_content" id="aside_content"><div class="card-widget card-info"><div class="card-content"><div class="card-info-avatar is-center"><img class="avatar-img" src="/img/%E5%A4%B4%E5%83%8F2.jpg" onerror="this.onerror=null;this.src='/img/friend_404.gif'" alt="avatar"/><div class="author-info__name">Li YunBO</div><div class="author-info__description">给自己的警言：不要止步不前，不要因循守缺，不要纸上谈兵，不要不思进取，不要一直不要！</div></div><div class="card-info-data"><div class="card-info-data-item is-center"><a href="/archives/"><div class="headline">Articles</div><div class="length-num">193</div></a></div><div class="card-info-data-item is-center"><a href="/tags/"><div class="headline">Tags</div><div class="length-num">25</div></a></div><div class="card-info-data-item is-center"><a href="/categories/"><div class="headline">Categories</div><div class="length-num">18</div></a></div></div><a class="button--animated" id="card-info-btn" target="_blank" rel="noopener" href="https://gitee.com/Sobremesa_bolg"><i class="fab fa-github"></i><span>Follow Me</span></a><div class="card-info-social-icons is-center"><a class="social-icon" href="https://gitee.com/Sobremesa_bolg" target="_blank" title="Gitee"><i class="fab fa-github"></i></a></div></div></div><div class="card-widget card-announcement"><div class="card-content"><div class="item-headline"><i class="fas fa-bullhorn card-announcement-animation"></i><span>Announcement</span></div><div class="announcement_content">这是我的博客</div></div></div><div class="sticky_layout"><div class="card-widget card-recent-post"><div class="card-content"><div class="item-headline"><i class="fas fa-history"></i><span>Recent Post</span></div><div class="aside-list"><div class="aside-list-item"><a class="thumbnail" href="/2021/08/16/%E6%B5%8B%E8%AF%95%E8%AE%B0%E5%BD%95/" title="测试"><img src="/img/%E5%92%8C%E6%9C%8D%E5%B0%91%E5%A5%B3.jpg%20img/%E8%9C%98%E8%9B%9B%E4%BE%A0.jpg" onerror="this.onerror=null;this.src='/img/404.png'" alt="测试"/></a><div class="content"><a class="title" href="/2021/08/16/%E6%B5%8B%E8%AF%95%E8%AE%B0%E5%BD%95/" title="测试">测试</a><time datetime="2021-08-16T01:20:46.666Z" title="Created 2021-08-16 09:20:46">2021-08-16</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2021/08/16/%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E9%81%8D%E5%8E%86/" title="二叉树的遍历"><img src="/img/%E5%92%8C%E6%9C%8D%E5%B0%91%E5%A5%B3.jpg%20img/%E8%9C%98%E8%9B%9B%E4%BE%A0.jpg" onerror="this.onerror=null;this.src='/img/404.png'" alt="二叉树的遍历"/></a><div class="content"><a class="title" href="/2021/08/16/%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E9%81%8D%E5%8E%86/" title="二叉树的遍历">二叉树的遍历</a><time datetime="2021-08-15T16:00:00.000Z" title="Created 2021-08-16 00:00:00">2021-08-16</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2021/08/10/%E8%AE%A4%E7%9C%9F%E7%9A%84+Netty+%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90%EF%BC%88%E4%BA%8C%EF%BC%89/" title="认真的 Netty 源码解析（二）"><img src="/img/%E5%92%8C%E6%9C%8D%E5%B0%91%E5%A5%B3.jpg%20img/%E8%9C%98%E8%9B%9B%E4%BE%A0.jpg" onerror="this.onerror=null;this.src='/img/404.png'" alt="认真的 Netty 源码解析（二）"/></a><div class="content"><a class="title" href="/2021/08/10/%E8%AE%A4%E7%9C%9F%E7%9A%84+Netty+%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90%EF%BC%88%E4%BA%8C%EF%BC%89/" title="认真的 Netty 源码解析（二）">认真的 Netty 源码解析（二）</a><time datetime="2021-08-10T07:53:27.000Z" title="Created 2021-08-10 15:53:27">2021-08-10</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2021/08/10/%E8%AE%A4%E7%9C%9F%E7%9A%84+Netty+%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90%EF%BC%88%E4%B8%80%EF%BC%89/" title="认真的 Netty 源码解析（一）"><img src="/img/%E5%92%8C%E6%9C%8D%E5%B0%91%E5%A5%B3.jpg%20img/%E8%9C%98%E8%9B%9B%E4%BE%A0.jpg" onerror="this.onerror=null;this.src='/img/404.png'" alt="认真的 Netty 源码解析（一）"/></a><div class="content"><a class="title" href="/2021/08/10/%E8%AE%A4%E7%9C%9F%E7%9A%84+Netty+%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90%EF%BC%88%E4%B8%80%EF%BC%89/" title="认真的 Netty 源码解析（一）">认真的 Netty 源码解析（一）</a><time datetime="2021-08-10T07:53:15.000Z" title="Created 2021-08-10 15:53:15">2021-08-10</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2021/08/10/Java+%E9%9D%9E%E9%98%BB%E5%A1%9E+IO+%E5%92%8C%E5%BC%82%E6%AD%A5+IO/" title="Java 非阻塞 IO 和异步 IO"><img src="/img/%E5%92%8C%E6%9C%8D%E5%B0%91%E5%A5%B3.jpg%20img/%E8%9C%98%E8%9B%9B%E4%BE%A0.jpg" onerror="this.onerror=null;this.src='/img/404.png'" alt="Java 非阻塞 IO 和异步 IO"/></a><div class="content"><a class="title" href="/2021/08/10/Java+%E9%9D%9E%E9%98%BB%E5%A1%9E+IO+%E5%92%8C%E5%BC%82%E6%AD%A5+IO/" title="Java 非阻塞 IO 和异步 IO">Java 非阻塞 IO 和异步 IO</a><time datetime="2021-08-10T07:52:59.000Z" title="Created 2021-08-10 15:52:59">2021-08-10</time></div></div></div></div></div><div class="card-widget card-categories"><div class="card-content"><div class="item-headline"><i class="fas fa-folder-open"></i><span>Categories</span></div><ul class="card-category-list" id="aside-cat-list">
            <li class="card-category-list-item "><a class="card-category-list-link" href="/categories/Git/"><span class="card-category-list-name">Git</span><span class="card-category-list-count">1</span></a></li><li class="card-category-list-item "><a class="card-category-list-link" href="/categories/Java/"><span class="card-category-list-name">Java</span><span class="card-category-list-count">53</span></a></li><li class="card-category-list-item "><a class="card-category-list-link" href="/categories/MySql/"><span class="card-category-list-name">MySql</span><span class="card-category-list-count">22</span></a></li><li class="card-category-list-item "><a class="card-category-list-link" href="/categories/Redis/"><span class="card-category-list-name">Redis</span><span class="card-category-list-count">18</span></a></li><li class="card-category-list-item "><a class="card-category-list-link" href="/categories/Spring/"><span class="card-category-list-name">Spring</span><span class="card-category-list-count">11</span></a></li><li class="card-category-list-item "><a class="card-category-list-link" href="/categories/SpringBoot/"><span class="card-category-list-name">SpringBoot</span><span class="card-category-list-count">2</span></a></li><li class="card-category-list-item "><a class="card-category-list-link" href="/categories/Springboot/"><span class="card-category-list-name">Springboot</span><span class="card-category-list-count">1</span></a></li><li class="card-category-list-item "><a class="card-category-list-link" href="/categories/concurrency/"><span class="card-category-list-name">concurrency</span><span class="card-category-list-count">6</span></a></li>
            <li class="card-category-list-item more is-center"><a class="card-category-list-link-more" href="/categories/">
                <span>More</span><i class="fas fa-angle-right"></i></a></li>
            </ul></div></div><div class="card-widget card-tags"><div class="card-content"><div class="item-headline"><i class="fas fa-tags"></i><span>Tags</span></div><div class="card-tag-cloud"><a href="/tags/JVM/" style="font-size: 1.18em; color: #999ca1">JVM</a> <a href="/tags/Java/" style="font-size: 1.3em; color: #99a1ac">Java</a> <a href="/tags/Java-JVM/" style="font-size: 1.42em; color: #99a6b7">Java JVM</a> <a href="/tags/Java-Spring/" style="font-size: 1.22em; color: #999ea4">Java Spring</a> <a href="/tags/Java%E3%80%81%E9%9D%A2%E8%AF%95%E9%A2%98/" style="font-size: 1.38em; color: #99a4b4">Java、面试题</a> <a href="/tags/Java%E5%9F%BA%E7%A1%80/" style="font-size: 1.5em; color: #99a9bf">Java基础</a> <a href="/tags/Java%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/" style="font-size: 1.1em; color: #999">Java数据结构</a> <a href="/tags/Java%E9%A1%B9%E7%9B%AE/" style="font-size: 1.1em; color: #999">Java项目</a> <a href="/tags/MySql/" style="font-size: 1.46em; color: #99a7bb">MySql</a> <a href="/tags/MySql%E3%80%81%E9%9D%A2%E8%AF%95%E9%A2%98/" style="font-size: 1.14em; color: #999b9d">MySql、面试题</a> <a href="/tags/Redis/" style="font-size: 1.26em; color: #999fa8">Redis</a> <a href="/tags/Redis%E3%80%81%E9%9D%A2%E8%AF%95/" style="font-size: 1.1em; color: #999">Redis、面试</a> <a href="/tags/Spring-Java/" style="font-size: 1.22em; color: #999ea4">Spring Java</a> <a href="/tags/SpringBoot/" style="font-size: 1.1em; color: #999">SpringBoot</a> <a href="/tags/hexo%E3%80%81blog/" style="font-size: 1.1em; color: #999">hexo、blog</a> <a href="/tags/java/" style="font-size: 1.1em; color: #999">java</a> <a href="/tags/jvm-memory-management/" style="font-size: 1.1em; color: #999">jvm-memory-management</a> <a href="/tags/netty-source/" style="font-size: 1.14em; color: #999b9d">netty-source</a> <a href="/tags/redis/" style="font-size: 1.38em; color: #99a4b4">redis</a> <a href="/tags/spring-aop-intro/" style="font-size: 1.1em; color: #999">spring-aop-intro</a> <a href="/tags/spring-aop-source/" style="font-size: 1.1em; color: #999">spring-aop-source</a> <a href="/tags/%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86/" style="font-size: 1.1em; color: #999">内存管理</a> <a href="/tags/%E5%BE%AA%E7%8E%AF%E4%BE%9D%E8%B5%96/" style="font-size: 1.1em; color: #999">循环依赖</a> <a href="/tags/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/" style="font-size: 1.34em; color: #99a3b0">数据结构</a> <a href="/tags/%E9%97%AE%E9%A2%98/" style="font-size: 1.1em; color: #999">问题</a></div></div></div><div class="card-widget card-archives"><div class="card-content"><div class="item-headline"><i class="fas fa-archive"></i><span>Archives</span></div><ul class="card-archive-list"><li class="card-archive-list-item"><a class="card-archive-list-link" href="/archives/2021/08/"><span class="card-archive-list-date">August 2021</span><span class="card-archive-list-count">28</span></a></li><li class="card-archive-list-item"><a class="card-archive-list-link" href="/archives/2021/07/"><span class="card-archive-list-date">July 2021</span><span class="card-archive-list-count">14</span></a></li><li class="card-archive-list-item"><a class="card-archive-list-link" href="/archives/2021/06/"><span class="card-archive-list-date">June 2021</span><span class="card-archive-list-count">3</span></a></li><li class="card-archive-list-item"><a class="card-archive-list-link" href="/archives/2021/05/"><span class="card-archive-list-date">May 2021</span><span class="card-archive-list-count">8</span></a></li><li class="card-archive-list-item"><a class="card-archive-list-link" href="/archives/2021/04/"><span class="card-archive-list-date">April 2021</span><span class="card-archive-list-count">140</span></a></li></ul></div></div><div class="card-widget card-webinfo"><div class="card-content"><div class="item-headline"><i class="fas fa-chart-line"></i><span>Info</span></div><div class="webinfo"><div class="webinfo-item"><div class="item-name">Article :</div><div class="item-count">193</div></div><div class="webinfo-item"><div class="item-name">UV :</div><div class="item-count" id="busuanzi_value_site_uv"></div></div><div class="webinfo-item"><div class="item-name">PV :</div><div class="item-count" id="busuanzi_value_site_pv"></div></div><div class="webinfo-item"><div class="item-name">Last Push :</div><div class="item-count" id="last-push-date" data-lastPushDate="2021-09-16T09:01:00.524Z"></div></div></div></div></div></div></div></main><footer id="footer"><div id="footer-wrap"><div class="copyright">&copy;2020 - 2021 By Li YunBO</div><div class="framework-info"><span>Framework </span><a target="_blank" rel="noopener" href="https://hexo.io">Hexo</a><span class="footer-separator">|</span><span>Theme </span><a target="_blank" rel="noopener" href="https://github.com/jerryc127/hexo-theme-butterfly">Butterfly</a></div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="darkmode" type="button" title="Switch Between Light And Dark Mode"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside_config" type="button" title="Setting"><i class="fas fa-cog"></i></button><button id="go-up" type="button" title="Back To Top"><i class="fas fa-arrow-up"></i></button></div></div><div><script src="/js/utils.js"></script><script src="/js/main.js"></script><div class="js-pjax"><script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script></div><script id="click-heart" src="https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/click-heart.min.js" async="async" mobile="false"></script></div><script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"pluginModelPath":"assets/","model":{"jsonPath":"live2d-widget-model-koharu"},"display":{"position":"left","width":150,"height":300},"mobile":{"show":false},"rect":"opacity:0.7","log":false,"pluginJsPath":"lib/","pluginRootPath":"live2dw/","tagMode":false});</script></body></html>